// g++ test11.cpp -lpthread

#include <iostream>

void auto_const()
{
    const auto a = 1 + 1;
    constexpr auto b = 1 + a;
    int c = 2;
    const auto d = b + c;

    std::cout << a << " " << b << " " << d << std::endl;
}

void lambda()
{
    auto a = []() -> int
    { return 10 + 15; };
    auto b = 23;
    auto c = [a, b](int comp) mutable -> bool
    { return a() + ++b > comp; };

    std::cout << a() << " " << b << " " << c(49) << " " << c(49) << std::endl;
}

void except()
{
    int *p = nullptr;

    try
    {
        std::cout << *p << std::endl;
    }
    catch (std::exception &ex)
    {
        std::cout << ex.what() << std::endl;
    }

    try
    {
        std::cout << *p << std::endl;
    }
    catch (...)
    {
        std::cout << std::current_exception().__cxa_exception_type()->name() << std::endl;
    }
}

#include <cstdarg>

void var_args(int count, ...)
{
    va_list args;
    va_start(args, count);
    std::vprintf("%d %d %d\n", args);
}

template <typename... X>
void var_args2(X... args)
{
    std::printf("%d %d %d\n", args...);
}

template <typename T>
void temp_add(T n1, T n2)
{
    std::cout << "all:" << n1 + n2 << std::endl;
}

template <>
void temp_add(double n1, double n2)
{
    std::cout << "double:" << n1 + n2 << std::endl;
}

#include <type_traits>

void typeinfo()
{
    std::cout << "float:" << std::is_arithmetic<float>() << std::endl;
    std::cout << "string:" << std::is_array<std::string>() << " " << std::is_class<std::string>() << std::endl;
    std::cout << typeid(11.2).name() << " " << typeid(11).name() << " " << typeid("kdsjf").name() << std::endl;
}

#include <array>
#include <algorithm>
#include <bitset>
#include <tuple>

void container()
{
    std::array<int, 10> arr = {11, 22, 55};
    std::for_each(arr.begin(), arr.end(), [](int &n)
                  { std::cout << n << " "; });
    std::cout << std::endl;

    std::bitset<8> bb = 8;
    std::bitset<8> bs("00001010");
    std::bitset<8> bst("1010");
    std::cout << bb.to_string() << " " << bs.to_ulong() << " " << bst.to_ulong() << std::endl;

    std::pair<int, std::string> pa(13, "dsklfjsldf");
    std::cout << pa.first << " " << pa.second << std::endl;

    std::tuple<int, int, std::string, std::string> tp(1, 2, "sdf", "dsf");
    std::cout << std::tuple_size<decltype(tp)>::value << " " << std::get<1>(tp) << " " << typeid(std::tuple_element<1, decltype(tp)>::type).name() << std::endl;
}

#include <memory>

void mem()
{
    std::unique_ptr<char[]> uptr = std::make_unique<char[]>(15);
    uptr[0] = 'A';
    std::cout << uptr.get() << std::endl;
    std::unique_ptr<char[]> uptr2 = std::move(uptr);
    std::cout << uptr2.get() << std::endl;

    std::shared_ptr<char[]> sptr = std::make_shared<char[]>(10);
    std::weak_ptr<char[]> wptr = sptr;
    sptr[0] = 'B';
    std::cout << sptr.get() << " " << sptr.use_count() << " " << wptr.lock().get() << " " << wptr.use_count() << std::endl;

    int fd = 23;
    auto fd_deleter = [](int *pfd)
    {
        std::cout << "release " << *pfd << std::endl;
    };
    std::unique_ptr<int, decltype(fd_deleter)> fd_local_ptr(&fd, fd_deleter);
}

#include <atomic>
#include <condition_variable>
#include <thread>

std::atomic_int ai(5);
int num(3);
std::condition_variable cv;
std::mutex m;

void conc_thread1()
{
    ai.fetch_sub(3);
    std::cout << "ai" << ai.load() << std::endl;

    if (ai < 3)
    {
        std::unique_lock<std::mutex> lock(m);
        cv.wait(lock);

        std::cout << "ai" << ai.load() << std::endl;
    }
}

void conc_thread2()
{
    std::this_thread::sleep_for(std::chrono::seconds(5));

    ai++;
    std::cout << "ai" << ai.load() << std::endl;

    cv.notify_one();
}

#include <chrono>
#include <future>

void concurrent()
{
    std::thread(conc_thread1).detach();
    std::thread(conc_thread2).detach();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ai.load() << std::endl;

    std::packaged_task<int(int, int)> task([](int a, int b) -> int
                                           { return a * b; });
    auto res = task.get_future();
    task(3, 4);
    std::cout << res.get() << std::endl;

    task.reset();
    res = task.get_future();
    std::thread(std::move(task), 5, 6).join();
    std::cout << res.get() << std::endl;

    auto res1 = std::async([](int a, int b) -> int
                           { return a + b; },
                           3, 8);
    std::cout << res1.get() << std::endl;
}

#include <limits>

void some()
{
    std::cout << std::chrono::seconds(3).count() << std::endl;

    std::tm tm1 = {0, 16, 21, 4, 2, 2021 - 1900};
    std::time_t tt = std::mktime(&tm1);
    auto tp = std::chrono::system_clock::from_time_t(tt);
    auto du = std::chrono::system_clock::now() - tp;

    std::cout << std::chrono::duration_cast<std::chrono::seconds>(du).count() << std::endl;

    std::cout << std::numeric_limits<int>::min() << " " << std::numeric_limits<int>::max() << std::endl;

    std::cout << std::locale("").name() << std::endl;
}

#include <regex>

void regex()
{
    // 匹配
    std::string text = "Date:2017-10-10";
    auto pattern = "Date.(\\d{4})-(\\d{2}-(\\d{2}))";
    std::regex expr(pattern);

    // 一般第0组是整个正则表达式匹配结果
    std::match_results<std::string::const_iterator> res;
    if (std::regex_match(text, res, expr))
    {
        for (auto it = res.begin(); it != res.end(); it++)
        {
            std::cout << it->str() << std::endl;
        }
    }

    // 搜索
    text = "Date:2017-10-10 ~ 2017-10-15";
    expr = "(\\d{4})-(\\d{2}-(\\d{2}))";

    res = std::match_results<std::string::const_iterator>();
    if (std::regex_search(text, res, expr))
    {
        for (auto it = res.begin(); it != res.end(); it++)
        {
            std::cout << it->str() << std::endl;
        }
    }

    // 替换
    auto substitutes = "2017-10-12";

    auto ret = std::regex_replace(text, expr, substitutes);
    std::cout << ret << std::endl;
}

struct s1
{
};

struct s2
{
    uint8_t m1;
    uint16_t m2;
    uint32_t m3;
    uint32_t m4;
    uint64_t m5;
};

struct s3
{
    uint8_t m1 : 2;
    uint16_t m2 : 5;
    uint32_t m3 : 1;
    uint32_t m4 : 7;
    uint64_t m5 : 5;
};

struct s4
{
    uint8_t m1;
    uint16_t m2 alignas(8);
    uint32_t m3 alignas(2);
    uint32_t m4;
    uint64_t m5;
};

struct s5
{
    uint8_t m1;
    uint16_t m2 __attribute__((aligned(1)));
    uint32_t m3;
    uint32_t m4;
    uint64_t m5;
} __attribute__((aligned(1)));

#pragma pack(1)
struct s6
{
    uint8_t m1;
    uint16_t m2;
    uint32_t m3;
    uint32_t m4;
    uint64_t m5;
};

struct s7
{
    uint8_t m1 : 2;
    uint16_t m2 : 5;
    uint32_t m3 : 1;
    uint32_t m4 : 7;
    uint64_t m5 : 5;
};
#pragma pack()

#include <cstring>
#include <iomanip>

void struct_aligin()
{
    std::cout << "s1 len:" << sizeof(s1) << " " << alignof(s1) << std::endl;
    // 1 1
    std::cout << "s2 len:" << sizeof(s2) << " " << alignof(s2) << std::endl;
    // 24 8

    s2 sv = {1, 2, 3, 4, 5};
    std::cout << "s2 value:";
    uint8_t ba[25] = {0};
    memcpy(ba, &sv, sizeof(sv));
    for (auto i = 0; i < 25; i++)
    {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << (uint16_t)ba[i] << " ";
    }
    std::cout << std::endl;
    // 01 30 02 00 03 00 00 00 04 00 00 00 08 00 00 00 05 00 00 00 00 00 00 00 00

    std::cout << "s3 len:" << sizeof(s3) << " " << alignof(s3) << std::endl;
    // 8 8

    std::cout << "s4 len:" << sizeof(s4) << " " << alignof(s4) << " " << alignof(s4::m1) << " " << alignof(s4::m2) << " " << alignof(s4::m3) << std::endl;
    // 20 8 1 8 4

    std::cout << "s5 len:" << sizeof(s5) << " " << alignof(s5) << " " << alignof(s5::m1) << " " << alignof(s5::m2) << " " << alignof(s5::m3) << std::endl;
    // 18 8 1 2 4

    std::cout << "s6 len:" << sizeof(s6) << " " << alignof(s6) << " " << alignof(s6::m1) << " " << alignof(s6::m2) << " " << alignof(s6::m3) << std::endl;
    // 13 1 1 1 1

    std::cout << "s7 len:" << sizeof(s7) << " " << alignof(s7) << std::endl;
}

long double operator"" _mm(long double x) { return x / 1000; }
long double operator"" _m(long double x) { return x; }
long double operator"" _km(long double x) { return x * 1000; }

struct RGBA
{
    uint8_t r, g, b, a;
    RGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
};

RGBA operator"" _RGBA(const char *str, size_t size)
{
    const char *r = nullptr, *g = nullptr, *b = nullptr, *a = nullptr;
    for (const char *p = str; p != str + size; ++p)
    {
        if (*p == 'r')
            r = p + 1;
        if (*p == 'g')
            g = p + 1;
        if (*p == 'b')
            b = p + 1;
        if (*p == 'a')
            a = p + 1;
    }
    if (r == nullptr || g == nullptr || b == nullptr)
        throw;
    if (a == nullptr)
    {
        return RGBA(atoi(r), atoi(g), atoi(b), 0);
    }
    else
    {
        return RGBA(atoi(r), atoi(g), atoi(b), atoi(a));
    }
}

std::ostream &operator<<(std::ostream &os, const RGBA &color)
{
    return os << "r=" << (int)color.r << " g=" << (int)color.g << " b=" << (int)color.b << " a=" << (int)color.a << std::endl;
}

size_t operator"" _len(char const *str, size_t size)
{
    return size;
}

void literal()
{
    std::cout << 1.0_mm << " " << sizeof(1.0_mm) << std::endl; // 0.001
    std::cout << 1.0_m << std::endl;                           // 1
    std::cout << 1.0_km << std::endl;                          // 1000

    //自定义字面量来表示RGBA对象
    std::cout << "r255 g255 b255 a40"_RGBA << std::endl;

    std::cout << "mike"_len << std::endl; // 4
}

// \u6ca1\u95ee\u9898
void test_once()
{
	for (auto i = 0; i < 10; i++)
	{
		static std::once_flag once;
		std::call_once(once, []()
		{
			std::cout << "call once" << std::endl;
		});

		std::cout << "call" << std::endl;

		usleep(100 * 1000);
	}
}

// g++ test11.cpp -lpthread -lstdc++fs
// #ifdef __has_include
// #if __has_include(<filesystem>)
// #include <filesystem>
// using std::filesystem::directory_iterator;
// using std::filesystem::path;
// #else
// #include <experimental/optional>
// using std::experimental::filesystem::v1::directory_iterator;
// using std::experimental::filesystem::v1::path;
// #endif
// #endif

// void test_experimental()
// {
//     int count = 0;
//     for (auto &v : directory_iterator("."))
//     {
//         //
//         std::string fileName = v.path().filename().string();
//         std::cout << "fileName= " << fileName << std::endl;

//         //
//         std::string extensionName = v.path().extension().string();
//         std::cout << "extensionName= " << extensionName << std::endl;
//     }

//     system("pause");
// }

int main()
{
    auto_const();
    lambda();
    // except();
    var_args(3, 24, 334, 11);
    var_args2(24, 35, 63);
    temp_add(12, 33);
    temp_add(12.3, 33.1);
    typeinfo();
    container();
    mem();
    concurrent();
    some();
    regex();
    struct_aligin();
    literal();

    //test_experimental();

    return 0;
}
